Linux服务器

推荐列表 站点导航

当前位置:首页 > 服务器技术 > Linux服务器 >

iptables的端口范围映射

来源:网络整理  作者:网友投稿  发布时间:2020-12-29 06:51
使用iptables来进行端口映射我们似乎比较熟悉,指定一个范围的端口映射好像也略懂一二,但实际测试结果却不尽人意...

使用iptables来进行端口映射我们似乎比较熟悉,指定一个范围的端口映射好像也略懂一二,但实际测试结果却不尽人意。

 

单个端口映射

一般而言要在路由器里实现一条端口映射规则,需要两个iptables规则,一条是目的地址转换一条是源地址转换。 如下(192.168.40.200是wan口地址,10.0.0.150是LAN侧主机地址):

iptables -t nat -I PREROUTING -p tcp -d 192.168.40.200 --dport 23 -j DNAT --to 10.0.0.150:23

iptables -t nat -I POSTROUTING -p tcp -s 10.0.0.150 --sport 23 -j SNAT --to 192.168.40.200:23

 

范围端口映射

查看man iptables可知,范围端口映射规则也挺简单,匹配源时写为--sport port[:port],target时写为[ipaddr][-ipaddr][:port[-port]]。即上面单个的端口映射规则改为这种形式:

iptables -t nat -I PREROUTING -p tcp -d 192.168.40.200 --dport 23:100 -j DNAT --to 10.0.0.150:23-100

重点不在于规则怎么写,而是范围端口映射时是怎么映射?因为它可以少对多也可以多对少。例如配置[10-12]映射到[100-102],我怎么知道端口11会映射到具体那个端口,101吗? [100-200]映射到[10-20]时又会怎么样呢?

如果测试一下第一个问题会发现总是映射到100端口,不是想象的101端口。

 

代码跟踪

内核代码一向难度较高,这里也只是浅浅的忽悠一下。

跟踪一下DNAT target的动作,DNAT动作的代码在net/ipv4/netfilter/nf_nat_rule.c里的ipt_dnat_target()函数,然后进入nf_nat_setup_info() ==》 get_unique_tuple()。

get_unique_tuple函数

1.static void

2.get_unique_tuple(struct nf_conntrack_tuple *tuple,

3.         const struct nf_conntrack_tuple *orig_tuple,

4.         const struct nf_nat_range *range,

5.         struct nf_conn *ct,

6.         enum nf_nat_manip_type maniptype)

7.{

8.    struct net *net = nf_ct_net(ct);

9.    const struct nf_nat_protocol *proto;

10.    u16 zone = nf_ct_zone(ct);

11.

12.    /* 1) If this srcip/proto/src-proto-part is currently mapped,

13.       and that same mapping gives a unique tuple within the given

14.       range, use that.

15.

16.       This is only required for source (ie. NAT/masq) mappings.

17.       So far, we don't do local source mappings, so multiple

18.       manips not an issue.  */

19.    if (maniptype == IP_NAT_MANIP_SRC &&

20.        !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {

21.        if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) {

22.            pr_debug("get_unique_tuple: Found current src map\n");

23.            if (!nf_nat_used_tuple(tuple, ct))

24.                return;

25.        }

26.    }

27.    printk("%s(%d)\n", __FUNCTION__, __LINE__);

28.    /* 2) Select the least-used IP/proto combination in the given

29.       range. */

30.    *tuple = *orig_tuple;

31.    find_best_ips_proto(zone, tuple, range, ct, maniptype);

32.

33.    /* 3) The per-protocol part of the manip is made to map into

34.       the range to make a unique tuple. */

35.

36.    rcu_read_lock();

37.    proto = __nf_nat_proto_find(orig_tuple->dst.protonum);

38.

39.    /* Only bother mapping if it's not already in range and unique */

40.    if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM) &&

41.        (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||

42.         proto->in_range(tuple, maniptype, &range->min, &range->max)) &&

43.        !nf_nat_used_tuple(tuple, ct))

44.        goto out;

45.

46.    /* Last change: get protocol to try to obtain unique tuple. */

47.    proto->unique_tuple(tuple, range, maniptype, ct);

48.out:

49.    printk("%s(%d)\n", __FUNCTION__, __LINE__);

50.    rcu_read_unlock();

51.}

52.

重点在第40行的判断,里面的proto->in_range(tuple, maniptype, &range->min, &range->max)会判断原tuple的端口是否在映射的端口范围内,如果在那就基本要直接goto out了。否则会进入proto->unique_tuple ==> tcp_unique_tuple ==>nf_nat_proto_unique_tuple。

nf_nat_proto_unique_tuple函数,看这一句就好了。

1.for (i = 0; ; ++off) {

2.        *portptr = htons(min + off % range_size);

3.        if (++i != range_size && nf_nat_used_tuple(tuple, ct))

4.            continue;

5.        if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))

6.            *rover = off;

7.        return;

8.    }

portptr为传出的参数,就是映射到这个端口啦。min为映射端口范围的最小值,off为偏移,大多数时候为0,range_size为端口范围大小。所以进到这里一般情况下,就会映射范围端口里面最小的端口。

 

结论

当匹配的端口在映射端口的区间内时,那么端口号不会被修改。如果匹配端口不在映射端口的区间内,则大多数情况下映射端口号为最小的端口号,即映射端口号是不可预测的。

举例: [1000-2000] 映射到[1000-2000]时会一一映射。

[1000-2000] 映射到[3000-4000]结果不可预知,一般会映射到3000端口。

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/server/fwq/10581.shtml

相关文章
Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

iptables的端口范围映射

2020-12-29 编辑:网友投稿

使用iptables来进行端口映射我们似乎比较熟悉,指定一个范围的端口映射好像也略懂一二,但实际测试结果却不尽人意。

 

单个端口映射

一般而言要在路由器里实现一条端口映射规则,需要两个iptables规则,一条是目的地址转换一条是源地址转换。 如下(192.168.40.200是wan口地址,10.0.0.150是LAN侧主机地址):

iptables -t nat -I PREROUTING -p tcp -d 192.168.40.200 --dport 23 -j DNAT --to 10.0.0.150:23

iptables -t nat -I POSTROUTING -p tcp -s 10.0.0.150 --sport 23 -j SNAT --to 192.168.40.200:23

 

范围端口映射

查看man iptables可知,范围端口映射规则也挺简单,匹配源时写为--sport port[:port],target时写为[ipaddr][-ipaddr][:port[-port]]。即上面单个的端口映射规则改为这种形式:

iptables -t nat -I PREROUTING -p tcp -d 192.168.40.200 --dport 23:100 -j DNAT --to 10.0.0.150:23-100

重点不在于规则怎么写,而是范围端口映射时是怎么映射?因为它可以少对多也可以多对少。例如配置[10-12]映射到[100-102],我怎么知道端口11会映射到具体那个端口,101吗? [100-200]映射到[10-20]时又会怎么样呢?

如果测试一下第一个问题会发现总是映射到100端口,不是想象的101端口。

 

代码跟踪

内核代码一向难度较高,这里也只是浅浅的忽悠一下。

跟踪一下DNAT target的动作,DNAT动作的代码在net/ipv4/netfilter/nf_nat_rule.c里的ipt_dnat_target()函数,然后进入nf_nat_setup_info() ==》 get_unique_tuple()。

get_unique_tuple函数

1.static void

2.get_unique_tuple(struct nf_conntrack_tuple *tuple,

3.         const struct nf_conntrack_tuple *orig_tuple,

4.         const struct nf_nat_range *range,

5.         struct nf_conn *ct,

6.         enum nf_nat_manip_type maniptype)

7.{

8.    struct net *net = nf_ct_net(ct);

9.    const struct nf_nat_protocol *proto;

10.    u16 zone = nf_ct_zone(ct);

11.

12.    /* 1) If this srcip/proto/src-proto-part is currently mapped,

13.       and that same mapping gives a unique tuple within the given

14.       range, use that.

15.

16.       This is only required for source (ie. NAT/masq) mappings.

17.       So far, we don't do local source mappings, so multiple

18.       manips not an issue.  */

19.    if (maniptype == IP_NAT_MANIP_SRC &&

20.        !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {

21.        if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) {

22.            pr_debug("get_unique_tuple: Found current src map\n");

23.            if (!nf_nat_used_tuple(tuple, ct))

24.                return;

25.        }

26.    }

27.    printk("%s(%d)\n", __FUNCTION__, __LINE__);

28.    /* 2) Select the least-used IP/proto combination in the given

29.       range. */

30.    *tuple = *orig_tuple;

31.    find_best_ips_proto(zone, tuple, range, ct, maniptype);

32.

33.    /* 3) The per-protocol part of the manip is made to map into

34.       the range to make a unique tuple. */

35.

36.    rcu_read_lock();

37.    proto = __nf_nat_proto_find(orig_tuple->dst.protonum);

38.

39.    /* Only bother mapping if it's not already in range and unique */

40.    if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM) &&

41.        (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||

42.         proto->in_range(tuple, maniptype, &range->min, &range->max)) &&

43.        !nf_nat_used_tuple(tuple, ct))

44.        goto out;

45.

46.    /* Last change: get protocol to try to obtain unique tuple. */

47.    proto->unique_tuple(tuple, range, maniptype, ct);

48.out:

49.    printk("%s(%d)\n", __FUNCTION__, __LINE__);

50.    rcu_read_unlock();

51.}

52.

重点在第40行的判断,里面的proto->in_range(tuple, maniptype, &range->min, &range->max)会判断原tuple的端口是否在映射的端口范围内,如果在那就基本要直接goto out了。否则会进入proto->unique_tuple ==> tcp_unique_tuple ==>nf_nat_proto_unique_tuple。

nf_nat_proto_unique_tuple函数,看这一句就好了。

1.for (i = 0; ; ++off) {

2.        *portptr = htons(min + off % range_size);

3.        if (++i != range_size && nf_nat_used_tuple(tuple, ct))

4.            continue;

5.        if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))

6.            *rover = off;

7.        return;

8.    }

portptr为传出的参数,就是映射到这个端口啦。min为映射端口范围的最小值,off为偏移,大多数时候为0,range_size为端口范围大小。所以进到这里一般情况下,就会映射范围端口里面最小的端口。

 

结论

当匹配的端口在映射端口的区间内时,那么端口号不会被修改。如果匹配端口不在映射端口的区间内,则大多数情况下映射端口号为最小的端口号,即映射端口号是不可预测的。

举例: [1000-2000] 映射到[1000-2000]时会一一映射。

[1000-2000] 映射到[3000-4000]结果不可预知,一般会映射到3000端口。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/server/fwq/10581.shtml

相关文章

风云图片

推荐阅读

返回Linux服务器频道首页